import React from 'react';
import { useMemo , memo } from 'react';
// import { useCallback } from 'react';
import { useState } from 'react';

// const Child = (props) => {
//   console.log('child被执行了')
//   return (
//     <div>child - { props.b }</div>
//   )
// }
// 如果是类组件  class Child extends React.PureComponent {}
//  memo包裹下的组件会在更新的时候浅比较props，从而达到减少渲染的目的  性能优化 
const Child = memo((props) => {
  console.log('child被执行了')
  return (
    <div>child - { props.b }</div>
  )
})

const Com = React.memo(({b}) => {
  console.log('com被执行了')
  return (
    <div>com - { b }</div>
  )
})

const ChildTwo = ({b})=>{
    console.log(' ChildTwo 被执行了')
    return (
      <div>ChildTwo - { b }</div>
    )
}

const App = () => {
  const [a, setA] = useState(0)
  // const [b] = useState(100)
  const [b, setB] = useState(100)

  const [list, setList] = useState([1, 2, 3, 4, 5])

  const add = () => {
    setA(a + 1)
  }

  const addB = () => {
    setB(b + 1)
  }

  // 每次更新生成一个新的引用，意味这属性发生改变
  // const testFn = () => {}
  // 如果记住这个函数 useCallback 以及 useMemo ，从而达到提升组件性能的目的
  // const testFn = useCallback(() => { // useCallback结构
  //   return (event) => { // 真正的函数实现
  //   }
  // }, []) // 依赖值的改变，重新生成新的引用
  const testFn = useMemo((event) => { // 真正的函数
  }, [])

  // 函数式组件中，通常使用useMemo可以实现计算属性
  // const doubleA = a * 2 // 不推荐
  const doubleA = useMemo(() => {
    return a * 2
  }, [a])

  const len = useMemo(() => {
    return list.length
  }, [list])

  return (
    <div>
      <button onClick={ () => {
        const arr = JSON.parse(JSON.stringify(list)) // 深拷贝  
        arr.push(len+1)
        setList(arr)
        
      }}>追加数据</button>{list} - {len}
      <button onClick={ add }>a加1</button> 
      <h3>{ a } - { doubleA } - { len } </h3>
      <button onClick={ addB }>b加1</button>
      <h3> { b }</h3>
      {/* 理想情况 b的值发生改变，Child 组件才被重新渲染 */}
      {/* 可以使用高阶组件 React.memo() 包裹一下Child组件 */}
      <Child b={ b }/>

      {/* 组件的状态发生改变，组件重新渲染，重新渲染，就会给函数生成一个新的地址，意味着全新的一个属性 */}
      <Com b = { b } testFn = { testFn }/>

      <ChildTwo b={b} />
    </div>
  );
};

export default App;
